#include "stdafx.h"
#include "EXHeaderCtrl.h"

#define DT_DEFAULT	((UINT)-1)
#define FH_PROPERTY_SPACING			1
#define FH_PROPERTY_ARROW			2
#define FH_PROPERTY_STATICBORDER	3
#define FH_PROPERTY_DONTDROPCURSOR	4
#define FH_PROPERTY_DROPTARGET		5
#define FLATHEADER_TEXT_MAX	80
#define XHEADERCTRL_NO_IMAGE		0
#define XHEADERCTRL_UNCHECKED_IMAGE	1
#define XHEADERCTRL_CHECKED_IMAGE	2

// CEXHeaderCtrl

#define DEF_TIMER_LEAVE_ID 1
#define DEF_TIMER_LEAVE_ELPASE 10

#define WM_DEF_CUSTOMIZE_HEADER (WM_USER+1)

IMPLEMENT_DYNAMIC(CEXHeaderCtrl, CHeaderCtrl)

CEXHeaderCtrl::CEXHeaderCtrl()
{
	m_cr3DHighLight   = ::GetSysColor(COLOR_3DHIGHLIGHT);
	m_cr3DShadow      = ::GetSysColor(COLOR_3DSHADOW);
	m_cr3DFace        = ::GetSysColor(COLOR_3DFACE);
	m_crBtnText       = ::GetSysColor(COLOR_BTNTEXT);

	m_pListCtrl       = NULL;
	m_nFormat         = DT_DEFAULT;
	m_rgbText         = m_crBtnText;
	m_bDividerLines   = TRUE;
	m_iSpacing        = 6;
	m_sizeArrow.cx    = 8;
	m_sizeArrow.cy    = 8;
	m_sizeImage.cx    = 0;
	m_sizeImage.cy    = 0;
	m_bStaticBorder   = FALSE;
	m_nDontDropCursor = 0;
	m_bResizing       = FALSE;
	m_nClickFlags     = 0;

	m_bLMouseDown	= FALSE;
	m_bTracking		= FALSE;
	m_uHeaderBitmapID = 0;
}

CEXHeaderCtrl::~CEXHeaderCtrl()
{

}


BEGIN_MESSAGE_MAP(CEXHeaderCtrl, CHeaderCtrl)
	ON_COMMAND(WM_DEF_CUSTOMIZE_HEADER, &CEXHeaderCtrl::OnDefCustomizeHeaderNotify)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_SYSCOLORCHANGE()
	ON_MESSAGE(HDM_INSERTITEM,			&CEXHeaderCtrl::OnInsertItem)
	ON_MESSAGE(HDM_DELETEITEM,			&CEXHeaderCtrl::OnDeleteItem)
	ON_MESSAGE(HDM_SETIMAGELIST,		&CEXHeaderCtrl::OnSetImageList)
	ON_MESSAGE(HDM_LAYOUT,				&CEXHeaderCtrl::OnLayout)
	ON_NOTIFY_REFLECT(NM_RCLICK,		&CEXHeaderCtrl::OnNMRclick)
	ON_MESSAGE(WM_MOUSELEAVE,			&CEXHeaderCtrl::OnMouseLeave)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_TIMER()
	ON_WM_WINDOWPOSCHANGING()
	ON_WM_WINDOWPOSCHANGED()
END_MESSAGE_MAP()



// CEXHeaderCtrl message handlers


BOOL CEXHeaderCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam)
{
	switch(wParam)
	{
	case FH_PROPERTY_SPACING:
		m_iSpacing = (int)lParam;
		break;

	case FH_PROPERTY_ARROW:
		m_sizeArrow.cx = LOWORD(lParam);
		m_sizeArrow.cy = HIWORD(lParam);
		break;

	case FH_PROPERTY_STATICBORDER:
		m_bStaticBorder = (BOOL)lParam;
		break;

	case FH_PROPERTY_DONTDROPCURSOR:
		m_nDontDropCursor = (UINT)lParam;
		break;

	default:
		return FALSE;
	}

	Invalidate();
	return TRUE;
}

void CEXHeaderCtrl::SetResSet(CEXBaseResSet* pResSet)
{
  m_pHeaderResSet = (CEXHeaderCtrlResSet *)pResSet;
  
  SetFont(m_pHeaderResSet->m_font);
  SetBkgndColor(m_pHeaderResSet->m_crBkColor);
  SetTextColor(m_pHeaderResSet->m_crText);

  if(m_pHeaderResSet->m_nType == HEADER_CTRL)
    SetHeaderBitmap(m_pHeaderResSet->m_nImgId);
}

void CEXHeaderCtrl::DrawCtrl(CDC* pDC)
{
	CRect rectClient;
	GetClientRect(&rectClient);

	if (m_uHeaderBitmapID)
	{
		CBitmap bmpBkgnd;
		bmpBkgnd.LoadBitmap(m_uHeaderBitmapID);

		BITMAP bmInfo;
		bmpBkgnd.GetBitmap(&bmInfo);

		CDC dcSrc;
		dcSrc.CreateCompatibleDC(pDC);

		CBitmap * pOldSrc = dcSrc.SelectObject(&bmpBkgnd);

		CDC dcDest;
		dcDest.CreateCompatibleDC(pDC);

		CBitmap * pOldDest = NULL;

		m_bmpNormal.DeleteObject();
		m_bmpNormal.CreateCompatibleBitmap(pDC, bmInfo.bmWidth/4, 
                                      rectClient.Height());
		pOldDest = dcDest.SelectObject(&m_bmpNormal);
		dcDest.StretchBlt(0, 0, bmInfo.bmWidth/4, rectClient.Height()/3,
			&dcSrc, 0, 0, bmInfo.bmWidth/4, bmInfo.bmHeight/3, SRCCOPY); // top

		dcDest.StretchBlt(0, rectClient.Height()-(rectClient.Height()/3), 
                      bmInfo.bmWidth/4, rectClient.Height()/3, &dcSrc, 0, 
                      bmInfo.bmHeight-(bmInfo.bmHeight/3), bmInfo.bmWidth/4, 
                      bmInfo.bmHeight/3, SRCCOPY); // bottom

		dcDest.StretchBlt(0, rectClient.Height()/3, bmInfo.bmWidth/4, 
                      rectClient.Height()-(rectClient.Height()/3*2), &dcSrc, 0, 
                      bmInfo.bmHeight/3, bmInfo.bmWidth/4, bmInfo.bmHeight -
                      (bmInfo.bmHeight/3*2), SRCCOPY); // middle

		dcDest.SelectObject(pOldDest);

		m_bmpFocus.DeleteObject();
		m_bmpFocus.CreateCompatibleBitmap(pDC,bmInfo.bmWidth/4,rectClient.Height());
		pOldDest = dcDest.SelectObject(&m_bmpFocus);
		
    dcDest.StretchBlt(0, 0, bmInfo.bmWidth/4, rectClient.Height()/3,
			                &dcSrc, (bmInfo.bmWidth/4), 0, bmInfo.bmWidth/4, 
                      bmInfo.bmHeight/3, SRCCOPY); // top
		
    dcDest.StretchBlt(0, rectClient.Height()-(rectClient.Height()/3), 
                      bmInfo.bmWidth/4, rectClient.Height()/3, &dcSrc, 
                      (bmInfo.bmWidth/4), bmInfo.bmHeight-(bmInfo.bmHeight/3), 
                      bmInfo.bmWidth/4, bmInfo.bmHeight/3, SRCCOPY); // bottom
		
    dcDest.StretchBlt(0, rectClient.Height()/3, bmInfo.bmWidth/4, 
                      rectClient.Height()-(rectClient.Height()/3*2), &dcSrc, 
                      (bmInfo.bmWidth/4), bmInfo.bmHeight/3, bmInfo.bmWidth/4, 
                      bmInfo.bmHeight-(bmInfo.bmHeight/3*2), SRCCOPY); // middle
		
    dcDest.SelectObject(pOldDest);

		m_bmpSelect.DeleteObject();
		m_bmpSelect.CreateCompatibleBitmap(pDC,bmInfo.bmWidth/4,rectClient.Height());
		pOldDest = dcDest.SelectObject(&m_bmpSelect);
		
    dcDest.StretchBlt(0, 0, bmInfo.bmWidth/4, rectClient.Height()/3,
			                &dcSrc, (bmInfo.bmWidth/4*2), 0, bmInfo.bmWidth/4, 
                      bmInfo.bmHeight/3, SRCCOPY); // top
		
    dcDest.StretchBlt(0, rectClient.Height()-(rectClient.Height()/3), 
                      bmInfo.bmWidth/4, rectClient.Height()/3, &dcSrc, 
                      (bmInfo.bmWidth/4*2), bmInfo.bmHeight-(bmInfo.bmHeight/3), 
                      bmInfo.bmWidth/4, bmInfo.bmHeight/3, SRCCOPY); // bottom
		
    dcDest.StretchBlt(0, rectClient.Height()/3, bmInfo.bmWidth/4, 
                      rectClient.Height()-(rectClient.Height()/3*2), &dcSrc, 
                      (bmInfo.bmWidth/4*2), bmInfo.bmHeight/3, bmInfo.bmWidth/4, 
                      bmInfo.bmHeight-(bmInfo.bmHeight/3*2), SRCCOPY); // middle

		dcDest.SelectObject(pOldDest);
	}

	CRect rectClip;
	if (pDC->GetClipBox(&rectClip) == ERROR)
		return;

	CRect rectItem;

	HCURSOR hCursor = GetCursor();
	HCURSOR hCursorArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);

	if (!m_uHeaderBitmapID)
		pDC->FillSolidRect(rectClip, m_cr3DFace);

	int iItems = GetItemCount();
	ASSERT(iItems >= 0);

	CPen penHighLight(PS_SOLID, 1, m_cr3DHighLight);
	CPen penShadow(PS_SOLID, 1, m_cr3DShadow);

	CPen* pPen = pDC->GetCurrentPen();

	CFont* pFont = pDC->SelectObject(GetFont());

	pDC->SetBkColor(m_cr3DFace);
	pDC->SetTextColor(m_crBtnText);

	int iWidth = 0;

	DWORD dwStyle = ::GetWindowLong(GetParent()->GetSafeHwnd(), GWL_STYLE);	
	POINT pointMouse;
	::GetCursorPos(&pointMouse);
	::ScreenToClient(m_hWnd, &pointMouse);	

	for (int i = 0; i < iItems; i++)
	{
		int iItem = OrderToIndex(i);

		TCHAR szText[FLATHEADER_TEXT_MAX];

		HDITEM hditem;
		hditem.mask = HDI_WIDTH|HDI_FORMAT|HDI_TEXT|HDI_IMAGE|HDI_BITMAP|HDI_LPARAM;
		hditem.pszText = szText;
		hditem.cchTextMax = sizeof(szText);
		VERIFY(GetItem(iItem, &hditem));

		VERIFY(GetItemRect(iItem, rectItem));

		if (m_uHeaderBitmapID)
		{
			if( !(dwStyle&LVS_NOSORTHEADER) && 
				rectClient.PtInRect(pointMouse) &&
				rectItem.PtInRect(pointMouse) && 
				hCursor == hCursorArrow)
			{
				if( m_bLMouseDown )
					DrawMouseDown(pDC, rectItem);
				else
				{
					DrawMouseOver(pDC, rectItem);
				}
			}
			else
				DrawMouseOut(pDC, rectItem);
		}

		if (rectItem.right >= rectClip.left || rectItem.left <= rectClip.right)
		{
			if (hditem.fmt & HDF_OWNERDRAW)
			{
				DRAWITEMSTRUCT disItem;
				disItem.CtlType = ODT_BUTTON;
				disItem.CtlID = GetDlgCtrlID();
				disItem.itemID = iItem;
				disItem.itemAction = ODA_DRAWENTIRE;
				disItem.itemState = 0;
				disItem.hwndItem = m_hWnd;
				disItem.hDC = pDC->m_hDC;
				disItem.rcItem = rectItem;
				disItem.itemData = 0;

				DrawItem(&disItem);
			}
			else
			{
				rectItem.DeflateRect(m_iSpacing, 0);
				DrawItem(pDC, rectItem, &hditem);
				rectItem.InflateRect(m_iSpacing, 0);
			}

      if (m_bDividerLines)		
      {
        pDC->SelectObject(&penShadow);
        pDC->MoveTo(rectItem.right-1, rectItem.top+2);
        pDC->LineTo(rectItem.right-1, rectItem.bottom-2);

        pDC->SelectObject(&penHighLight);
        pDC->MoveTo(rectItem.right, rectItem.top+2);
        pDC->LineTo(rectItem.right, rectItem.bottom-2);
      }
		}
		iWidth += hditem.cxy;
	}

	rectItem.left = iWidth;
	rectItem.right = rectClient.Width();

	if (m_uHeaderBitmapID)
	{
		if( !(dwStyle&LVS_NOSORTHEADER) && 
			rectItem.PtInRect(pointMouse) && 
			hCursor == hCursorArrow )
		{
			if( !m_bLMouseDown )
			{
				DrawMouseOver(pDC, rectItem);
			}
			else
				DrawMouseDown(pDC, rectItem);
		}
		else
			DrawMouseOut(pDC, rectItem);
	}
	else
	{
		if (iWidth > 0)
		{
			rectClient.right = rectClient.left + iWidth;
			pDC->Draw3dRect(rectClient, m_cr3DHighLight, m_cr3DShadow);
		}
	}

	pDC->SelectObject(pFont);
	pDC->SelectObject(pPen);

	penHighLight.DeleteObject();
	penShadow.DeleteObject();
}

void CEXHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT)
{
	ASSERT(FALSE);
}

void CEXHeaderCtrl::DrawItem(CDC* pDC, CRect rect, LPHDITEM lphdi)
{
	ASSERT(lphdi->mask & HDI_FORMAT);

	int iWidth = 0;

	CBitmap* pBitmap = NULL;
	BITMAP BitmapInfo;

	if (lphdi->fmt & HDF_BITMAP)
	{
		ASSERT(lphdi->mask & HDI_BITMAP);
		ASSERT(lphdi->hbm);

		pBitmap = CBitmap::FromHandle(lphdi->hbm);
		if (pBitmap)
			VERIFY(pBitmap->GetObject(sizeof(BITMAP), &BitmapInfo));
	}

	rect.left += ((iWidth = DrawImage(pDC, rect, lphdi, FALSE)) != 0) ? 
		iWidth + m_iSpacing : 0;

	rect.right -= ((iWidth = DrawBitmap(pDC, rect, lphdi, pBitmap, 
                                     &BitmapInfo, TRUE)) != 0) ? 
                                     iWidth + m_iSpacing : 0;

	LOGFONT lf = {0};
	GetFont()->GetLogFont(&lf);
	lf.lfWeight  = FW_BOLD;

	CFont font;
	font.CreateFontIndirect(&lf);
	CFont * pOld = pDC->SelectObject(&font);

	pDC->SetTextColor(RGB(58, 60, 75));
	DrawText(pDC, rect, lphdi);

	pDC->SelectObject(pOld);
}

int CEXHeaderCtrl::DrawImage(CDC* pDC, CRect rect, LPHDITEM lphdi, BOOL bRight)
{
	int iWidth = 0;

	if (lphdi->lParam)
	{
		CImageList* pImageList = GetImageList();

		if (pImageList && (rect.Width() > 0))
		{
			POINT point;

			point.y = rect.CenterPoint().y - ((m_sizeImage.cy+1) >> 1);

			if (bRight)
				point.x = rect.right - m_sizeImage.cx;
			else
				point.x = rect.left;

			SIZE size;
			size.cx = rect.Width() < m_sizeImage.cx ? rect.Width() : m_sizeImage.cx;
			size.cy = m_sizeImage.cy;

			pImageList->DrawIndirect(pDC, lphdi->iImage, point, size, CPoint(0, 0));

			iWidth = m_sizeImage.cx;
		}
		else if (rect.Width() > 0)
		{
			CRect chkboxrect = rect;

			// center the checkbox

			int h = 13;	// height and width are the same
			chkboxrect.right = chkboxrect.left + h;
			chkboxrect.top = rect.top + (rect.Height() - h) / 2;
			chkboxrect.bottom = chkboxrect.top + h;

			// fill rect inside checkbox with white
			COLORREF rgbBackground = pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
			pDC->FillSolidRect(&chkboxrect, ::GetSysColor(COLOR_WINDOW));

			// draw border
			CBrush brush(RGB(51,102,153));
			pDC->FrameRect(&chkboxrect, &brush);

			if (lphdi->iImage == XHEADERCTRL_CHECKED_IMAGE)
			{
				CPen blackpen(PS_SOLID, 1, RGB(51,153,51));
				CPen * pOldPen = pDC->SelectObject(&blackpen);

				// draw the checkmark
				int x = chkboxrect.left + 9;
				ASSERT(x < chkboxrect.right);
				int y = chkboxrect.top + 3;
				int i = 0;
				for (i = 0; i < 4; i++)
				{
					pDC->MoveTo(x, y);
					pDC->LineTo(x, y+3);
					x--;
					y++;
				}
				for (i = 0; i < 3; i++)
				{
					pDC->MoveTo(x, y);
					pDC->LineTo(x, y+3);
					x--;
					y--;
				}
				if (pOldPen)
					pDC->SelectObject(pOldPen);
			}

			pDC->SetBkColor(rgbBackground);

			iWidth = chkboxrect.Width();
		}
	}
	return iWidth;
}

int CEXHeaderCtrl::DrawBitmap(CDC* pDC, 
							 CRect rect, 
							 LPHDITEM lphdi, 
							 CBitmap* pBitmap, 
							 BITMAP* pBitmapInfo, 
							 BOOL bRight)
{
	UNUSED_ALWAYS(lphdi);

	int iWidth = 0;

	if (pBitmap)
	{
		iWidth = pBitmapInfo->bmWidth;
		if (iWidth <= rect.Width() && rect.Width() > 0)
		{
			POINT point;

			point.y = rect.CenterPoint().y - (pBitmapInfo->bmHeight >> 1);

			if (bRight)
				point.x = rect.right - iWidth;
			else
				point.x = rect.left;

			CDC dc;
			if (dc.CreateCompatibleDC(pDC) == TRUE) 
			{
				CBitmap * pOldBitmap = dc.SelectObject(pBitmap);
				iWidth = pDC->BitBlt(
					point.x, point.y, 
					pBitmapInfo->bmWidth, pBitmapInfo->bmHeight, 
					&dc, 
					0, 0, 
					SRCCOPY
					) ? iWidth:0;
				dc.SelectObject(pOldBitmap);
			}
			else 
				iWidth = 0;
		}
		else
			iWidth = 0;
	}

	return iWidth;
}

int CEXHeaderCtrl::DrawText(CDC* pDC, CRect rect, LPHDITEM lphdi)
{
	CSize size = pDC->GetTextExtent(lphdi->pszText);

#if 0  // -----------------------------------------------------------
	pDC->SetTextColor(RGB(0,0,255));

	if (rect.Width() > 0 && lphdi->mask & HDI_TEXT && lphdi->fmt & HDF_STRING)
	{
		size = pDC->GetTextExtent(lphdi->pszText);

		// always center column headers
		pDC->DrawText(lphdi->pszText, -1, rect, 
			DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);
	}
#endif // -----------------------------------------------------------

	//+++

	if (rect.Width() > 0 && lphdi->mask & HDI_TEXT && lphdi->fmt & HDF_STRING)
	{
		pDC->SetTextColor(m_rgbText);
		pDC->SetBkMode(TRANSPARENT); // SH

		UINT nFormat = m_nFormat;

		if (nFormat == DT_DEFAULT)
		{
			// default to whatever alignment the column is set to

			if (lphdi->fmt & LVCFMT_CENTER)
				nFormat = DT_CENTER;
			else if (lphdi->fmt & LVCFMT_RIGHT)
				nFormat = DT_RIGHT;
			else
				nFormat = DT_LEFT;
 		}

		pDC->DrawText(lphdi->pszText, -1, rect, 
			nFormat | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER);
	}

	size.cx = rect.Width() > size.cx ? size.cx : rect.Width();

	return size.cx > 0 ? size.cx : 0;
}

LRESULT CEXHeaderCtrl::OnInsertItem(WPARAM, LPARAM)
{
	return Default();
}

LRESULT CEXHeaderCtrl::OnDeleteItem(WPARAM, LPARAM)
{
	return Default();
}

LRESULT CEXHeaderCtrl::OnSetImageList(WPARAM, LPARAM lParam)
{
	CImageList* pImageList;
	pImageList = CImageList::FromHandle((HIMAGELIST)lParam);

	IMAGEINFO info;
	if (pImageList->GetImageInfo(0, &info))
	{
		m_sizeImage.cx = info.rcImage.right - info.rcImage.left;
		m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;
	}

	return Default();
}

LRESULT CEXHeaderCtrl::OnLayout(WPARAM, LPARAM lParam)
{
	LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam;

	if (m_bStaticBorder)
		lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2;

	return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
}

void CEXHeaderCtrl::OnSysColorChange() 
{
	CHeaderCtrl::OnSysColorChange();

	m_cr3DHighLight = ::GetSysColor(COLOR_3DHIGHLIGHT);
	m_cr3DShadow    = ::GetSysColor(COLOR_3DSHADOW);
	m_cr3DFace      = ::GetSysColor(COLOR_3DFACE);
	m_crBtnText     = ::GetSysColor(COLOR_BTNTEXT);
}

BOOL CEXHeaderCtrl::OnEraseBkgnd(CDC* pDC) 
{
	return CHeaderCtrl::OnEraseBkgnd(pDC);
}

void CEXHeaderCtrl::OnPaint() 
{
	CPaintDC dc(this);

	CXMemDC MemDC(&dc);
	DrawCtrl(&MemDC);
}

void CEXHeaderCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
}

void CEXHeaderCtrl::OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult)
{
	CMenu menu;
	menu.CreatePopupMenu();

	menu.AppendMenu(MF_STRING, WM_DEF_CUSTOMIZE_HEADER, (LPCTSTR)L"Customize");

	POINT point = {0};
	GetCursorPos(&point);
	SetForegroundWindow();
	menu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
	menu.DestroyMenu();

	*pResult = 0;
}

void CEXHeaderCtrl::OnDefCustomizeHeaderNotify()
{
	if (GetParent())
		GetParent()->PostMessage(UM_CUSTOMIZE_HEADER, 0, (LPARAM)this);
}

void CEXHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
	if(!m_bTracking) 
	{
		SetTimer(DEF_TIMER_LEAVE_ID, DEF_TIMER_LEAVE_ELPASE, NULL);
		m_bTracking = TRUE;
		TRACKMOUSEEVENT t = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, 0 };
		if (::_TrackMouseEvent(&t)) 
		{
			m_bTracking = TRUE;
		}
	}
	else
	{
		if (!(nFlags & MK_LBUTTON))
			RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_UPDATENOW|RDW_INVALIDATE);
	}

	CHeaderCtrl::OnMouseMove(nFlags, point);
}

LRESULT CEXHeaderCtrl::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
	if (!m_bLMouseDown)
	{
		m_bTracking = FALSE;
		RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_UPDATENOW|RDW_INVALIDATE);
	}
	else
	{
		TRACKMOUSEEVENT t = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, 0 };
		::_TrackMouseEvent(&t);
	}

	return 0L;
}

void CEXHeaderCtrl::DrawMouseDown(CDC* pDC, CRect rect)
{
	CBrush brBkgnd;
	brBkgnd.CreatePatternBrush(&m_bmpSelect);
	pDC->FillRect(rect, &brBkgnd);
}

void CEXHeaderCtrl::DrawMouseOut(CDC* pDC, CRect rect)
{
	CBrush brBkgnd;
	brBkgnd.CreatePatternBrush(&m_bmpNormal);
	pDC->FillRect(rect, &brBkgnd);
}

void CEXHeaderCtrl::DrawMouseOver(CDC* pDC, CRect rect)
{
	CBrush brBkgnd;
	brBkgnd.CreatePatternBrush(&m_bmpFocus);
	pDC->FillRect(rect, &brBkgnd);
}

void CEXHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bLMouseDown = TRUE;
	RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_UPDATENOW|RDW_INVALIDATE);

	CHeaderCtrl::OnLButtonDown(nFlags, point);
}

void CEXHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
	m_bLMouseDown = FALSE;
	RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_UPDATENOW|RDW_INVALIDATE);

	CHeaderCtrl::OnLButtonUp(nFlags, point);
}

void CEXHeaderCtrl::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == DEF_TIMER_LEAVE_ID)
	{
		POINT ptCur;
		GetCursorPos(&ptCur);
		ScreenToClient(&ptCur);

		CRect rcClient;
		GetClientRect(rcClient);

		if (!rcClient.PtInRect(ptCur) && !m_bLMouseDown)
		{
			KillTimer(DEF_TIMER_LEAVE_ID);
			m_bTracking = FALSE;
			RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_UPDATENOW|RDW_INVALIDATE);
		}
	}

	CHeaderCtrl::OnTimer(nIDEvent);
}


void CEXHeaderCtrl::SetHeaderBitmap(UINT nID)
{
	m_uHeaderBitmapID = nID;
	RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_UPDATENOW|RDW_INVALIDATE);
}

void CEXHeaderCtrl::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
	if (m_uHeaderBitmapID && m_bmpNormal.GetSafeHandle())
	{
		BITMAP bmInfo = {0};
		m_bmpNormal.GetBitmap(&bmInfo);
		lpwndpos->cy = bmInfo.bmHeight;
	}
	else
		lpwndpos->cy = 18;

	CDC * pDC = GetDC();
	pDC->SaveDC();
	pDC->SelectObject(GetFont());
	CSize siFont = pDC->GetTextExtent(L"A");
	pDC->RestoreDC(-1);
	ReleaseDC(pDC);
	siFont.cy += 5;

	if (lpwndpos->cy < siFont.cy)
		lpwndpos->cy = siFont.cy;

	CHeaderCtrl::OnWindowPosChanging(lpwndpos);
}

void CEXHeaderCtrl::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
	if (m_uHeaderBitmapID && m_bmpNormal.GetSafeHandle())
	{
		BITMAP bmInfo = {0};
		m_bmpNormal.GetBitmap(&bmInfo);
		lpwndpos->cy = bmInfo.bmHeight;
	}
	else
		lpwndpos->cy = 18;

	CDC * pDC = GetDC();
	pDC->SaveDC();
	pDC->SelectObject(GetFont());
	CSize siFont = pDC->GetTextExtent(L"A");
	pDC->RestoreDC(-1);
	ReleaseDC(pDC);
	siFont.cy += 5;

	if (lpwndpos->cy < siFont.cy)
		lpwndpos->cy = siFont.cy;

	CHeaderCtrl::OnWindowPosChanged(lpwndpos);
}

void CEXHeaderCtrl::SetBkgndColor(COLORREF crHeader)
{
	m_cr3DFace = crHeader;

	Invalidate(FALSE);
}
